package com.app.controller;


import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.app.mapper.UserMapper;
import com.app.pojo.PaymentRecordsLog;
import com.app.pojo.User;
import com.app.service.IPaymentRecordsLogService;
import com.app.util.DistributedLockService;
import com.app.util.PriceUtils;
import com.app.util.Result;
import com.app.vo.PaymentRecordsLogVo;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

/**
 * <p>
 * 缴费记录表 前端控制器
 * </p>
 *
 * @author yoominic
 * @since 2024-07-29
 */
@Slf4j
@Api(tags = "缴费记录相关接口")
@RestController
@RequestMapping("/paymentRecordsLog")
public class PaymentRecordsLogController {

    @Autowired
    private IPaymentRecordsLogService paymentRecordsLogService;
    @Autowired
    private DistributedLockService distributedLockService;
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private WxPayService wxService;
    @Value("${wx.pay.mchId}")
    private String mchId;


    @ApiOperation(value = "分页查询当前用户的缴费记录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "当前页码", required = true, dataType = "Integer"),
            @ApiImplicitParam(name = "limit", value = "每页条数", required = true, dataType = "Integer")
    })
    @GetMapping("/getPaymentRecordslISTByUserId")
    public Result getPaymentRecordslISTByUserId(@RequestParam(value = "page", defaultValue = "1") Integer page,
                                                @RequestParam(value = "limit", defaultValue = "10") Integer limit,
                                                HttpServletRequest request) {
        String token = request.getHeader("token");
        if (token == null) {
            return Result.error( "token不存在");
        }
        Object loginIdByToken = StpUtil.getLoginIdByToken(token);
        if (loginIdByToken == null) {
            Result result = new Result(401, "登录失效");
            return result;
        }
        String userId = loginIdByToken.toString();
        User user = userMapper.selectById(userId);
        if (user == null) {
            return Result.error( "用户不存在");
        }
        PaymentRecordsLogVo vo = paymentRecordsLogService.getPaymentRecordslISTByUserId(userId, page, limit);
        return Result.success(vo);
    }


    @ApiOperation(value = "创建缴费订单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "account", value = "用户账号", required = true, dataType = "String"),
//            @ApiImplicitParam(name = "userName", value = "用户姓名", required = true, dataType = "String"),
//            @ApiImplicitParam(name = "companyId", value = "缴费单位id", required = true, dataType = "Integer"),
            @ApiImplicitParam(name = "companyName", value = "单位名称", required = true, dataType = "String"),
//            @ApiImplicitParam(name = "userAddress", value = "用户地址", required = true, dataType = "String"),
            @ApiImplicitParam(name = "payMoney", value = "缴费金额", required = true, dataType = "Double")
    })
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/createPayGasOrder")
    public synchronized Result createPayGasOrder(@RequestBody PaymentRecordsLog paymentRecordsLog, HttpServletRequest request) {
        String token = request.getHeader("token");
        if (token == null) {
            return Result.error( "token不存在");
        }
        Object loginIdByToken = StpUtil.getLoginIdByToken(token);
        if (loginIdByToken == null) {
            Result result = new Result(401, "登录失效");
            return result;
        }
        String userId = loginIdByToken.toString();
        User user = userMapper.selectById(userId);
        if (user == null) {
            return Result.error( "用户不存在");
        }
        boolean lockAcquired = this.distributedLockService.acquireLock("createRechargeOrder", String.valueOf(StpUtil.getLoginIdAsLong())); // 锁的超时时间为10秒
        if (!lockAcquired) {
            // 如果无法获取锁，则直接返回
            return Result.error("操作频繁,请勿重复操作");
        }
        Object result = paymentRecordsLogService.createPayGasOrder(paymentRecordsLog,Integer.valueOf(userId));
        return Result.success(result);
    }


    /**
     * 解析订单通知结果
     *
     * @param xmlData xml数据
     * @return {@link String}
     * @throws WxPayException wx支付例外
     */
    @ApiOperation(value = "解析订单通知结果")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "xmlData", value = "微信回调通知xml数据", required = true, dataType = "String")
    })
    @PostMapping("/parseOrderNotifyResult")
    public Object parseOrderNotifyResult(@RequestBody String xmlData) throws WxPayException {
        final WxPayOrderNotifyResult notifyResult = this.wxService.switchoverTo(mchId).parseOrderNotifyResult(xmlData);
        log.info("【异步通知】处理后的数据data={}", JSONUtil.toJsonStr(notifyResult));
        if (notifyResult.getAttach().equals("燃气缴费充值")) {
            log.info("【燃气缴费支付回调】" + LocalDateTimeUtil.now());
            this.paymentRecordsLogService.parseOrderNotifyResult(notifyResult.getOutTradeNo(), PriceUtils.fenToYuan(Double.valueOf(notifyResult.getTotalFee())));
        }
        return WxPayNotifyResponse.success("成功");
    }



    //解析退款通知结果
    @PostMapping("/receiveWechatRefundInfo")
    public Object receiveWechatRefundInfo(@RequestBody String xmlData) throws WxPayException {
        final WxPayRefundNotifyResult result = this.wxService.switchoverTo(mchId).parseRefundNotifyResult(xmlData);
        log.info("【异步通知】处理后的数据data={}", JSONUtil.toJsonStr(result));
        if (!StrUtil.isBlankIfStr(result.getReqInfo().getOutTradeNo())) {
            String typeText = result.getReqInfo().getRefundAccount();
            if (StrUtil.isNotBlank(typeText)) {
                if (typeText.equals("REFUND_SOURCE_RECHARGE_FUNDS")) {
                    this.paymentRecordsLogService.receiveWechatRefundInfo(result.getReqInfo().getOutTradeNo(), result.getReqInfo().getRefundStatus());
                }
            }
        }
        return WxPayNotifyResponse.success("成功");
    }



}

